﻿using System.Collections.Specialized;
using System.ComponentModel.Design;
using Microsoft.Practices.Common;
using Microsoft.Practices.ComponentModel;
using Microsoft.Practices.RecipeFramework;
using Sixeyed.CodeGeneration.Metadata;
using Sixeyed.Guidance.CodeGeneration.ValueProviders.Helpers;

namespace Sixeyed.Guidance.CodeGeneration.ValueProviders
{
    /// <summary>
    /// Provides configured <see cref="Sixeyed.CodeGeneration.Metadata.SourceConfiguration"/> value
    /// </summary>
    [ServiceDependency(typeof(IDictionaryService))]
    public class SourceConfigurationValueProvider : ValueProvider, IAttributesConfigurable
    {
        private SourceConfiguration _sourceConfiguration;

        /// <summary>
        /// Gets/sets the metadata source configuration
        /// </summary>
        public SourceConfiguration SourceConfiguration
        {
            get 
            {
                if (this._sourceConfiguration == null)
                {
                    this._sourceConfiguration = new SourceConfiguration();
                }
                return _sourceConfiguration; 
            }
            set { _sourceConfiguration = value; }
        }

        /// <summary>
        /// Configures provider, loading metadata source assembly configuration from arguments
        /// </summary>
        /// <param name="attributes">Argument dictionary</param>
        public void Configure(StringDictionary attributes)
        {
            //all arguments are optional:
            this.SourceConfiguration.SourceTypeName = ValueProviderHelper.GetOptionalArgumentValue(attributes, ArgumentName.SourceTypeName);
            this.SourceConfiguration.SourceName = ValueProviderHelper.GetOptionalArgumentValue(attributes, ArgumentName.SourceName);
            this.SourceConfiguration.SourceUri = ValueProviderHelper.GetOptionalArgumentValue(attributes, ArgumentName.SourceUri);
            this.SourceConfiguration.ProviderName = ValueProviderHelper.GetOptionalArgumentValue(attributes, ArgumentName.ProviderName);
            //validate the configuration is complete:
            this.SourceConfiguration.Validate();
        }

        /// <summary>
        /// Provides updated argument value, if not already populated
        /// </summary>
        /// <param name="currentValue">Current argument value</param>
        /// <param name="newValue">New argument value</param>
        /// <returns>Whether argument value was updated</returns>
        public override bool OnBeginRecipe(object currentValue, out object newValue)
        {
            bool updated = false;
            //only update if the value isn't set:
            if (currentValue != null)
            {
                newValue = null;
            }
            else
            {
                newValue = this.SourceConfiguration;
                updated = true;
            }
            return updated;
        }

        private struct ArgumentName
        {
            public const string SourceTypeName = "SourceTypeName";
            public const string SourceName = "SourceName";
            public const string SourceUri = "SourceUri";
            public const string ProviderName = "ProviderName";
        }
    }
}
